/*	
 *				
 *					ISNW ---- It is a war.It is not warcraft!
 *
 *
 *					Author:					zhoukeli(haxixi_keli)
 *					Filename:				rect.h
 *					CreateTime:				2008/12/14
 *					ModifyTime:				2008/12/14
 */

#ifndef __ISNW_RECT_H__
#define __ISNW_RECT_H__

#include "isnwTypes.h"
#include "vector2d.h"

namespace ISNW
{
namespace core
{
	template<typename T>
	class rect
	{
	public:
		//! constructor
		rect(){}
		rect(const vector2d<T>& p1,const vector2d<T>& p2):LeftLowPoint(p1),RightUpPoint(p2){}

	public:
		//! operator
		bool operator == (const rect<T>& other) const{return (LeftLowPoint == other.LeftLowPoint && RightUpPoint == other.RightUpPoint);}
		bool operator != (const rect<T>& other) const{return !(*this == other);}

		rect<T>& operator = (const rect<T>& other){LeftLowPoint = other.LeftLowPoint;RightUpPoint = other.RightUpPoint;return *this;}



	public:
		//! functions
		rect<T>& set(const vector2d<T>& p1,const vector2d<T>& p2)
		{
			LeftLowPoint = p1;
			RightUpPoint = p2;

			return *this;
		}

		bool ispointin(const vector2d<T>& point) const
		{
			return (point >= LeftLowPoint && point <= RightUpPoint);
		}

		bool ispointtotalin(const vector2d<T>& point) const
		{
			return (point > LeftLowPoint && point < RightUpPoint);
		}

		bool getIntersectWithRect(const rect<T>& other,rect<T>& out) const
		{
			vector2d<T> new_left_low;
			vector2d<T> new_right_up;

			new_left_low.x = core::_max_<T>(LeftLowPoint.x,other.LeftLowPoint.x);
			new_left_low.y = core::_max_<T>(LeftLowPoint.y,other.LeftLowPoint.y);

			new_right_up.x = core::_min_<T>(RightUpPoint.x,other.RightUpPoint.x);
			new_right_up.y = core::_min_<T>(RightUpPoint.y,other.RightUpPoint.y);

			if(new_right_up >= new_left_low)
			{
				out.set(new_left_low,new_right_up);

				return true;
			}

			return false;
		}

		T getwidth() const
		{
			return (RightUpPoint.x - LeftLowPoint.x);
		}

		T getheight() const
		{
			return (RightUpPoint.y - LeftLowPoint.y);
		}

		T getarea() const
		{
			return getwidth() * getheight();
		}

		rect<T>& addpoint(const vector2d<T>& point)
		{
			if(LeftLowPoint.x > point.x) LeftLowPoint.x = point.x;
			if(LeftLowPoint.y > point.y) LeftLowPoint.y = point.y;

			if(RightUpPoint.x < point.x) RightUpPoint.x = point.x;
			if(RightUpPoint.y > point.y) RightUpPoint.y = point.y;

			return *this;
		}

		void repair()
		{
			T exchange;
			if(LeftLowPoint.x > RightUpPoint.x){exchange = LeftLowPoint.x;LeftLowPoint.x = RightUpPoint.x;RightUpPoint.x = exchange;}
			if(LeftLowPoint.y > RightUpPoint.y){exchange = LeftLowPoint.y;LeftLowPoint.y = RightUpPoint.y;RightUpPoint.y = exchange;}
		}

	public:
		vector2d<T> LeftLowPoint;
		vector2d<T> RightUpPoint;
	};

	//! typedef for float rect
	typedef rect<f32> rectf;
	//! typedef for int rect
	typedef rect<s32> recti;

} // end namespace core
} // end namespace ISNW
#endif